package cn.wiseda.finance.utils.encode;
/**
 * The Class ByteUtil.
 */
public abstract class ByteUtil
{

    /** The Constant ZERO. */
    public static final int ZERO = 0;

    /** The Constant ONE. */
    public static final int ONE = 1;

    /** The Constant TWO. */
    public static final int TWO = 2;

    /** The Constant THREE. */
    public static final int THREE = 3;

    /** The Constant FOUR. */
    public static final int FOUR = 4;

    /** The Constant FIVE. */
    public static final int FIVE = 5;

    /** The Constant SIX. */
    public static final int SIX = 6;

    /** The Constant SEVEN. */
    public static final int SEVEN = 7;

    /** The Constant EIGHT. */
    public static final int EIGHT = 8;

    /** The Constant NINE. */
    public static final int NINE = 9;

    /** The Constant THREE_BYTE_WIDTH. */
    public static final int THREE_BYTES_SIZE = 24;

    /** The Constant FIVE_BYTE_WIDTH. */
    public static final int FIVE_BYTES_SIZE = 40;

    /** The Constant SIX_BYTE_WIDTH. */
    public static final int SIX_BYTES_SIZE = 48;

    /** The Constant SEVEN_BYTE_WIDTH. */
    public static final int SEVEN_BYTES_SIZE = 56;

    /** The Constant FULL_ONE_BYTE. */
    public static final short MAX_BYTE = 0xff;

    /** The Constant HALF_BYTE. */
    public static final int HALF_BYTE = 0xf;

    /** The Constant LONG_WIDTH. */
    public static final int LONG_WIDTH = 8;

    /** The Constant INT_WIDTH. */
    public static final int INT_WIDTH = 4;

    /** The Constant SHORT_WIDTH. */
    public static final int SHORT_WIDTH = 2;

    /** The Constant DEFAULT_WIDTH. */
    public static final int DEFAULT_WIDTH = 16;

    /**
     * Bytes to int.
     *
     * @param bytes the bytes
     *
     * @return the int
     */
    public static int bytesToInt(byte[] bytes)
    {
        int tmp = bytes[THREE] & MAX_BYTE;
        tmp |= (bytes[TWO] & MAX_BYTE) << Byte.SIZE;
        tmp |= (bytes[ONE] & MAX_BYTE) << Short.SIZE;
        tmp |= (bytes[ZERO] & MAX_BYTE) << THREE_BYTES_SIZE;
        return tmp;
    }

    /**
     * Bytes to int.
     *
     * @param bytes the bytes
     * @param offset the offset
     *
     * @return the int
     */
    public static int bytesToInt(byte[] bytes, int offset)
    {
        int tmp = bytes[offset + THREE] & MAX_BYTE;
        tmp |= (bytes[offset + TWO] & MAX_BYTE) << Byte.SIZE;
        tmp |= (bytes[offset + ONE] & MAX_BYTE) << Short.SIZE;
        tmp |= (bytes[offset] & MAX_BYTE) << THREE_BYTES_SIZE;
        return tmp;
    }

    /**
     * Bytes to long.
     *
     * @param bytes the bytes
     *
     * @return the long
     */
    public static long bytesToLong(byte[] bytes)
    {
        long tmp = bytes[SEVEN] & MAX_BYTE;
        tmp |= (bytes[SIX] & MAX_BYTE) << Byte.SIZE;
        tmp |= (bytes[FIVE] & MAX_BYTE) << Short.SIZE;
        tmp |= (bytes[FOUR] & MAX_BYTE) << THREE_BYTES_SIZE;
        tmp |= (long) (bytes[THREE] & MAX_BYTE) << Integer.SIZE;
        tmp |= (long) (bytes[TWO] & MAX_BYTE) << FIVE_BYTES_SIZE;
        tmp |= (long) (bytes[ONE] & MAX_BYTE) << SIX_BYTES_SIZE;
        tmp |= (long) (bytes[ZERO] & MAX_BYTE) << SEVEN_BYTES_SIZE;
        return tmp;
    }

    /**
     * Bytes to long.
     *
     * @param bytes the bytes
     * @param offset the offset
     *
     * @return the long
     */
    public static long bytesToLong(byte[] bytes, int offset)
    {
        long tmp = bytes[offset + SEVEN] & MAX_BYTE;
        tmp |= (bytes[offset + SIX] & MAX_BYTE) << Byte.SIZE;
        tmp |= (bytes[offset + FIVE] & MAX_BYTE) << Short.SIZE;
        tmp |= (bytes[offset + FOUR] & MAX_BYTE) << THREE_BYTES_SIZE;
        tmp |= (long) (bytes[offset + THREE] & MAX_BYTE) << Integer.SIZE;
        tmp |= (long) (bytes[offset + TWO] & MAX_BYTE) << FIVE_BYTES_SIZE;
        tmp |= (long) (bytes[offset + ONE] & MAX_BYTE) << SIX_BYTES_SIZE;
        tmp |= (long) (bytes[offset + ZERO] & MAX_BYTE) << SEVEN_BYTES_SIZE;
        return tmp;
    }

    /**
     * Bytes to short.
     *
     * @param bytes the bytes
     *
     * @return the short
     */
    public static short bytesToShort(byte[] bytes)
    {
        return (short) ((bytes[ONE] & MAX_BYTE) | (bytes[ZERO] & MAX_BYTE) << Byte.SIZE);
    }

    /**
     * Bytes to short.
     *
     * @param bytes the bytes
     * @param offset the offset
     *
     * @return the short
     */
    public static short bytesToShort(byte[] bytes, int offset)
    {
        return (short) ((bytes[offset + ONE] & MAX_BYTE) | (bytes[offset] & MAX_BYTE) << Byte.SIZE);
    }

    /**
     * Compare.
     *
     * @param bytes1 the bytes1
     * @param offset1 the offset1
     * @param bytes2 the bytes2
     * @param offset2 the offset2
     *
     * @return true, if successful
     */
    public static boolean compare(byte[] bytes1, int offset1, byte[] bytes2,
            int offset2)
    {
        if (offset1 + bytes2.length > offset2 + bytes1.length)
        {
            return false;
        }
        for (int i = 0; i < bytes2.length; ++i)
        {
            if (bytes1[i + offset1] != bytes2[i + offset2])
            {
                return false;
            }
        }
        return true;
    }

    /**
     * Compare.
     *
     * @param bytes1 the bytes1
     * @param bytes2 the bytes2
     *
     * @return true, if successful
     */
    public static boolean compare(byte[] bytes1, byte[] bytes2)
    {
        if (bytes1.length != bytes2.length)
        {
            return false;
        }
        return compare(bytes1, 0, bytes2, 0);
    }

    /**
     * 拼接两个字节数组，将第二个数组拼接到第一个后面.
     *
     * @param source1 第一个字节数组
     * @param source2 第二个字节数组
     *
     * @return 拼接后的字节数组
     */
    public static byte[] concat(byte[] source1, byte[] source2)
    {
        if (source1 == null)
        {
            throw new NullPointerException("source1 byte array is null");
        }
        if (source2 == null)
        {
            throw new NullPointerException("source2 byte array is null");
        }
        byte[] buffer = new byte[source1.length + source2.length];
        System.arraycopy(source1, 0, buffer, 0, source1.length);
        System.arraycopy(source2, 0, buffer, source1.length, source2.length);
        return buffer;
    }

    /**
     * Int to bytes.
     *
     * @param source the source
     *
     * @return the byte[]
     */
    public static byte[] intToBytes(int source)
    {
        byte[] bytes = new byte[INT_WIDTH];
        bytes[ZERO] = (byte) (source >> THREE_BYTES_SIZE);
        bytes[ONE] = (byte) (source >> Short.SIZE);
        bytes[TWO] = (byte) (source >> Byte.SIZE);
        bytes[THREE] = (byte) source;
        return bytes;
    }

    /**
     * Int to bytes.
     *
     * @param source the source
     * @param target the target
     * @param offset the offset
     */
    public static void intToBytes(int source, byte[] target, int offset)
    {
        target[offset] = (byte) (source >> THREE_BYTES_SIZE);
        target[offset + ONE] = (byte) (source >> Short.SIZE);
        target[offset + TWO] = (byte) (source >> Byte.SIZE);
        target[offset + THREE] = (byte) source;
    }

    /**
     * Long to bytes.
     *
     * @param source the source
     *
     * @return the byte[]
     */
    public static byte[] longToBytes(long source)
    {
        byte[] bytes = new byte[LONG_WIDTH];
        bytes[ZERO] = (byte) (source >> SEVEN_BYTES_SIZE);
        bytes[ONE] = (byte) (source >> SIX_BYTES_SIZE);
        bytes[TWO] = (byte) (source >> FIVE_BYTES_SIZE);
        bytes[THREE] = (byte) (source >> Integer.SIZE);
        bytes[FOUR] = (byte) (source >> THREE_BYTES_SIZE);
        bytes[FIVE] = (byte) (source >> Short.SIZE);
        bytes[SIX] = (byte) (source >> Byte.SIZE);
        bytes[SEVEN] = (byte) source;
        return bytes;
    }

    /**
     * Long to bytes.
     *
     * @param source the source
     * @param target the target
     * @param offset the offset
     */
    public static void longToBytes(long source, byte[] target, int offset)
    {
        target[offset] = (byte) (source >> SEVEN_BYTES_SIZE);
        target[offset + ONE] = (byte) (source >> SIX_BYTES_SIZE);
        target[offset + TWO] = (byte) (source >> FIVE_BYTES_SIZE);
        target[offset + THREE] = (byte) (source >> Integer.SIZE);
        target[offset + FOUR] = (byte) (source >> THREE_BYTES_SIZE);
        target[offset + FIVE] = (byte) (source >> Short.SIZE);
        target[offset + SIX] = (byte) (source >> Byte.SIZE);
        target[offset + SEVEN] = (byte) source;
    }

    /**
     * Short to bytes.
     *
     * @param source the source
     *
     * @return the byte[]
     */
    public static byte[] shortToBytes(short source)
    {
        byte[] bytes = new byte[SHORT_WIDTH];
        bytes[ZERO] = (byte) (source >> Byte.SIZE);
        bytes[ONE] = (byte) source;
        return bytes;
    }

    /**
     * Short to bytes.
     *
     * @param source the source
     * @param bytes the bytes
     * @param offset the offset
     */
    public static void shortToBytes(short source, byte[] bytes, int offset)
    {
        bytes[offset] = (byte) (source >> Byte.SIZE);
        bytes[offset + ONE] = (byte) source;
    }

    /**
     * Byte2string.
     *
     * @param b the b
     *
     * @return the string
     */
    public static String byteTwoString(byte[] b)
    {
        if (b == null)
        {
            return null;
        }
        StringBuilder strHEX = new StringBuilder();
        strHEX.append("0x ");
        for (int i = 0; i < b.length; ++i)
        {
            strHEX.append(Integer.toHexString(b[i] >> FOUR & HALF_BYTE));
            strHEX.append(Integer.toHexString(b[i] & HALF_BYTE));
            strHEX.append(' ');
        }
        return strHEX.toString();
    }
    
	private static void byte2hex(byte b, StringBuffer buf) {
		char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
				'E', 'F' };
		int high = ((b & 0xf0) >> 4);
		int low = (b & 0x0f);
		buf.append(hexChars[high]);
		buf.append(hexChars[low]);
	}

	/*
	 * Converts a byte array to hex string
	 */
	public static String toHexString(byte[] block) {
		StringBuffer buf = new StringBuffer();

		int len = block.length;

		for (int i = 0; i < len; i++) {
			byte2hex(block[i], buf);
		}
		return buf.toString();
	}

    public static void main(String[] args) {
		byte[] bs = intToBytes(10001);
		for (int i = 0; i < bs.length; i++) {
			System.out.print(bs[i] + " ");
		}
	}
}
